using JetBrains.Annotations;



namespace Fine.Collections.Const
{
    /// <summary>
    /// Immutable list. 
    /// Items can be same, nulls are allowed.
    /// </summary>
    /// <typeparam name="T">type of an item.</typeparam>
    public class ConstList<T> : ConstArray<T>
    {

        #region CONSTRUCTORS

        internal ConstList(int firstIndex, params T[] items) 
            : base(firstIndex, items, ArrSize(items), false)
        {}


        internal ConstList(int firstIndex, ConstArray<T> constArray)
            : base(firstIndex, constArray.arr, constArray.count, true)
        {}


        internal ConstList(int firstIndex, T[] array, int count, bool takeOwnership) 
            : base(firstIndex, array, count, takeOwnership) 
        {}


        private static int ArrSize(T[] array)
        {
            return array != null ? array.Length : 0;
        }

        #endregion


   
        #region ABSTRACT FUNCTIONS IMPLEMENTATION


        public override bool Contains(T item)
        {
            return IndexOf(item) != int.MinValue;
        }


        public override int CountOf(T item)
        {
            return CountOf(x => equator.Equals(x, item));
        }


        /// <summary>
        /// Looks for the first occurance of the specified item, 
        /// and returns its index.
        /// </summary>
        /// <param name="item">item to look for.</param>
        /// <returns>index of the found item in 
        ///          the <see cref="ConstArray{T}.FirstIndex"/>..<see cref="ConstArray{T}.LastIndex"/> range;
        ///          or <see cref="int.MinValue"/> if not found.</returns>
        public override int IndexOf(T item)
        {
            for (int i = 0; i < count; i++)
                if (equator.Equals(arr[i], item))
                    return firstIndex + i;
            return int.MinValue;
        }


        /// <summary>
        /// Returns itself. Does nothing.
        /// </summary>
        /// <returns>itself.</returns>
        [NotNull]
        public override ConstList<T> ToList()
        {
            return this;
        }


        /// <summary>
        /// Makes a constant set with items from this colleaction.
        /// </summary>
        /// <returns>constant set with this items.</returns>
        [NotNull]
        public override ConstSet<T> ToSet()
        {
            return new ConstHashSet<T>(firstIndex, arr, count, true, false);
        }


        #endregion



        #region OPERATORS


        /// <summary>
        /// Concatenates two lists.
        /// </summary>
        /// <seealso cref="CC.Concat{T}"/>
        /// <param name="listA">the first list.</param>
        /// <param name="listB">the second list.</param>
        /// <returns>concatenation of the given lists; with firtsIndex taken from the first operand.</returns>
        public static ConstList<T> operator + (ConstList<T> listA, ConstList<T> listB)
        {
            return CC.Concat(listA.firstIndex, listA, listB);
        }


        #endregion

    }
}